import { useEffect, useRef, useState } from 'react'
import moment from 'moment'
import { useStrategyBacktest, BASE_CAPITAL, useTradeMarkers } from './index'

function update (chart, data) {
}

const comment = () => {
  return <div>基于ZIG折线的Spring策略（完整版）。包含多个买卖信号：1) 买线(ZIG(3,10))向上穿越卖线(MA(买线,3))时买入；2) B(ZIG(3,10))向上穿越G(MA(B,2))时买入；3) 符合复杂条件AA时买入；4) 买线向下穿越卖线或G向上穿越B或出现顶部信号时卖出。</div>
}

// ZIG 指标计算：基于百分比变化
// type: 1=收盘价, 2=最高价, 3=最低价
// percent: 百分比阈值
function calculateZIG (dataList, type = 3, percent = 10) {
  if (dataList.length === 0) return []
  
  const result = []
  let lastExtremeValue = null
  let lastExtremeIndex = -1
  let lastDirection = null // 'up' or 'down'
  let pendingExtremeValue = null
  let pendingExtremeIndex = -1
  
  for (let i = 0; i < dataList.length; i++) {
    const candle = dataList[i]
    let value
    if (type === 1) {
      value = candle.close
    } else if (type === 2) {
      value = candle.high
    } else {
      value = candle.low
    }
    
    if (i === 0) {
      result.push(value)
      lastExtremeValue = value
      lastExtremeIndex = 0
      pendingExtremeValue = value
      pendingExtremeIndex = 0
      continue
    }
    
    if (lastDirection === null) {
      // 初始化方向：找到第一个明显的趋势方向
      if (value > lastExtremeValue) {
        const changePercent = ((value - lastExtremeValue) / lastExtremeValue) * 100
        if (changePercent >= percent) {
          // 上升超过阈值，确立上升趋势
          lastDirection = 'up'
          result.push(value)
          lastExtremeValue = value
          lastExtremeIndex = i
          pendingExtremeValue = value
          pendingExtremeIndex = i
        } else {
          // 继续跟踪可能的极值
          result.push(lastExtremeValue)
          pendingExtremeValue = value
          pendingExtremeIndex = i
        }
      } else if (value < lastExtremeValue) {
        const changePercent = ((lastExtremeValue - value) / lastExtremeValue) * 100
        if (changePercent >= percent) {
          // 下降超过阈值，确立下降趋势
          lastDirection = 'down'
          result.push(value)
          lastExtremeValue = value
          lastExtremeIndex = i
          pendingExtremeValue = value
          pendingExtremeIndex = i
        } else {
          // 继续跟踪可能的极值
          result.push(lastExtremeValue)
          pendingExtremeValue = value
          pendingExtremeIndex = i
        }
      } else {
        result.push(lastExtremeValue)
      }
    } else if (lastDirection === 'up') {
      // 上升趋势中
      if (value > pendingExtremeValue) {
        // 更新待确认的最高点
        pendingExtremeValue = value
        pendingExtremeIndex = i
        result.push(lastExtremeValue)
      } else {
        // 价格开始回落
        const downPercent = ((pendingExtremeValue - value) / pendingExtremeValue) * 100
        if (downPercent >= percent) {
          // 回落超过阈值，确认转折
          // 先更新到之前待确认的极值点
          if (pendingExtremeIndex > lastExtremeIndex) {
            // 更新到待确认的极值
            for (let j = lastExtremeIndex + 1; j <= pendingExtremeIndex; j++) {
              result[j] = pendingExtremeValue
            }
            lastExtremeValue = pendingExtremeValue
            lastExtremeIndex = pendingExtremeIndex
          }
          // 现在创建新的转折点
          result.push(value)
          lastDirection = 'down'
          lastExtremeValue = value
          lastExtremeIndex = i
          pendingExtremeValue = value
          pendingExtremeIndex = i
        } else {
          result.push(lastExtremeValue)
        }
      }
    } else {
      // 下降趋势中
      if (value < pendingExtremeValue) {
        // 更新待确认的最低点
        pendingExtremeValue = value
        pendingExtremeIndex = i
        result.push(lastExtremeValue)
      } else {
        // 价格开始回升
        const upPercent = ((value - pendingExtremeValue) / pendingExtremeValue) * 100
        if (upPercent >= percent) {
          // 回升超过阈值，确认转折
          // 先更新到之前待确认的极值点
          if (pendingExtremeIndex > lastExtremeIndex) {
            // 更新到待确认的极值
            for (let j = lastExtremeIndex + 1; j <= pendingExtremeIndex; j++) {
              result[j] = pendingExtremeValue
            }
            lastExtremeValue = pendingExtremeValue
            lastExtremeIndex = pendingExtremeIndex
          }
          // 现在创建新的转折点
          result.push(value)
          lastDirection = 'up'
          lastExtremeValue = value
          lastExtremeIndex = i
          pendingExtremeValue = value
          pendingExtremeIndex = i
        } else {
          result.push(lastExtremeValue)
        }
      }
    }
  }
  
  // 处理最后一个待确认的极值
  if (pendingExtremeIndex > lastExtremeIndex && pendingExtremeIndex < result.length) {
    for (let j = lastExtremeIndex + 1; j <= pendingExtremeIndex; j++) {
      result[j] = pendingExtremeValue
    }
  }
  
  return result
}

// 计算移动平均
function calculateMA (data, period) {
  if (data.length < period) return null
  const sum = data.slice(-period).reduce((acc, val) => acc + val, 0)
  return sum / period
}

// 计算 EMA
function calculateEMA (dataList, period, key = 'close') {
  if (dataList.length === 0) return []
  const alpha = 2 / (period + 1)
  const result = []
  let ema = null
  
  for (let i = 0; i < dataList.length; i++) {
    const value = typeof dataList[i] === 'number' ? dataList[i] : dataList[i][key]
    if (ema === null) {
      ema = value
    } else {
      ema = alpha * value + (1 - alpha) * ema
    }
    result.push(ema)
  }
  
  return result
}

// 计算 PEAKBARS - 获取最近的峰值距离当前位置的周期数
// type: 1=收盘价, 2=最高价, 3=最低价
// percent: 百分比阈值
// which: 1=最近的峰值, 2=倒数第二个峰值, ...
function calculatePEAKBARS (dataList, type, percent, which = 1) {
  if (dataList.length === 0) return []
  const zigValues = calculateZIG(dataList, type, percent)
  const result = []
  
  for (let i = 0; i < dataList.length; i++) {
    let peakBars = null
    let peakCount = 0
    
    // 向后查找峰值
    for (let j = i; j >= 0; j--) {
      if (j === 0) continue
      const currZig = zigValues[j]
      const prevZig = zigValues[j - 1]
      
      // 检测到峰值：前一个值小于当前值（向上转折）
      if (prevZig < currZig) {
        peakCount++
        if (peakCount === which) {
          peakBars = i - j
          break
        }
      }
    }
    
    result.push(peakBars)
  }
  
  return result
}

// 计算 TROUGHBARS - 获取最近的谷值距离当前位置的周期数
function calculateTROUGHBARS (dataList, type, percent, which = 1) {
  if (dataList.length === 0) return []
  const zigValues = calculateZIG(dataList, type, percent)
  const result = []
  
  for (let i = 0; i < dataList.length; i++) {
    let troughBars = null
    let troughCount = 0
    
    // 向后查找谷值
    for (let j = i; j >= 0; j--) {
      if (j === 0) continue
      const currZig = zigValues[j]
      const prevZig = zigValues[j - 1]
      
      // 检测到谷值：前一个值大于当前值（向下转折）
      if (prevZig > currZig) {
        troughCount++
        if (troughCount === which) {
          troughBars = i - j
          break
        }
      }
    }
    
    result.push(troughBars)
  }
  
  return result
}

// 计算 LLV - 最低值
function calculateLLV (dataList, period, key = 'low') {
  if (dataList.length === 0) return []
  const result = []
  
  for (let i = 0; i < dataList.length; i++) {
    const start = Math.max(0, i - period + 1)
    const end = i + 1
    const slice = dataList.slice(start, end)
    const values = slice.map(item => item[key])
    const minValue = Math.min(...values)
    result.push(minValue)
  }
  
  return result
}

// 计算 STD - 标准差
function calculateSTD (dataList, period, key = 'close') {
  if (dataList.length === 0) return []
  const result = []
  
  for (let i = 0; i < dataList.length; i++) {
    const start = Math.max(0, i - period + 1)
    const end = i + 1
    const slice = dataList.slice(start, end)
    const values = slice.map(item => item[key])
    
    if (values.length < 2) {
      result.push(0)
      continue
    }
    
    const mean = values.reduce((sum, val) => sum + val, 0) / values.length
    const variance = values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / values.length
    const std = Math.sqrt(variance)
    result.push(std)
  }
  
  return result
}

const INTERVAL_KEY = 'springInterval'

const SpringTools = (props) => {
  const [started, setStarted] = useState(false)
  const [autoRun, setAutoRun] = useState(false)
  const [finished, setFinished] = useState(false)
  const [data, setData] = useState([])
  const [currentIndex, setCurrentIndex] = useState(0)
  const [holding, setHolding] = useState(false)
  const [intervalMs, setIntervalMs] = useState(() => {
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(INTERVAL_KEY)
      if (stored) {
        const val = Number(stored)
        if (!Number.isNaN(val) && val >= 100 && val <= 5000) {
          return val
        }
      }
    }
    return 500
  })
  const intervalRef = useRef(intervalMs)
  const autoTimerRef = useRef(null)
  const tradeInfoRef = useRef({
    active: false,
    entryPrice: 0,
    entryTimestamp: null,
    entryIndex: -1,
    overlayId: null
  })
  const overlaysRef = useRef([])
  const { addTradeMarker, redrawTradeMarkers, clearTradeMarkers } = useTradeMarkers(props.chart)
  const {
    equityHistory,
    recordEquity,
    registerTrade,
    reset: resetBacktest,
    finalize,
    SummaryModal
  } = useStrategyBacktest()

  // 将 equityHistory 传递给父组件
  useEffect(() => {
    if (props.onEquityHistoryChange) {
      props.onEquityHistoryChange(equityHistory)
    }
  }, [equityHistory])

  useEffect(() => {
    return () => {
      if (autoTimerRef.current) {
        clearInterval(autoTimerRef.current)
      }
    }
  }, [])

  useEffect(() => {
    intervalRef.current = intervalMs
    if (typeof window !== 'undefined') {
      localStorage.setItem(INTERVAL_KEY, String(intervalMs))
    }
  }, [intervalMs])

  useEffect(() => {
    if (autoTimerRef.current) {
      clearInterval(autoTimerRef.current)
    }
    if (started && autoRun && !finished) {
      autoTimerRef.current = setInterval(() => {
        nextStep()
      }, intervalRef.current)
    }
    return () => {
      if (autoTimerRef.current) {
        clearInterval(autoTimerRef.current)
      }
    }
  }, [autoRun, started, finished, data, currentIndex])

  const removeTradeOverlay = () => {
    if (tradeInfoRef.current.overlayId && props.chart?.current) {
      try {
        props.chart.current.removeOverlay(tradeInfoRef.current.overlayId)
      } catch (e) {
        // ignore removal failures
      }
    }
    tradeInfoRef.current.overlayId = null
  }

  const loadRandomDataset = async () => {
    const stocks = props.stocks ?? []
    if (!stocks.length) {
      return
    }
    const tradable = stocks.filter(stock => {
      return ((stock.code.startsWith('60') && stock.code.endsWith('SH')) ||
        (stock.code.startsWith('00') && stock.code.endsWith('SZ')) ||
        (stock.code.startsWith('30') && stock.code.endsWith('SZ'))) &&
        !stock.name.includes('ST')
    })
    if (!tradable.length) {
      return
    }
    const randomStock = tradable[Math.floor(Math.random() * tradable.length)]
    const dates = (props.dates ?? []).filter(date => {
      return date / 1000 >= randomStock.open && moment.unix(date / 1000).year() <= 2021
    })
    if (!dates.length) {
      return
    }
    const randomDate = dates[Math.floor(Math.random() * dates.length)]
    const dailyData = await props.getKlines(randomStock.code, '1d', randomDate, 600)
    if (!dailyData || !dailyData.length) {
      return
    }
    // 从第50项开始回测（保留前50个数据用于指标计算）
    const startIndex = Math.min(50, dailyData.length - 1)
    const initialData = dailyData.slice(0, startIndex)
    setData(dailyData)
    setCurrentIndex(startIndex)
    setHolding(false)
    setFinished(false)
    removeTradeOverlay()
    clearTradeMarkers()
    tradeInfoRef.current = {
      active: false,
      entryPrice: 0,
      entryTimestamp: null,
      entryIndex: -1,
      overlayId: null
    }
    if (props.trader?.reset) {
      props.trader.reset()
    }
    resetBacktest()
    applyChart(initialData)
    const initialTimestamp = initialData.length ? initialData[initialData.length - 1].timestamp : Date.now()
    recordEquity(initialTimestamp, props.trader?.equity ?? BASE_CAPITAL)
    setStarted(true)
    props.setInfoDisplay?.(false)
  }

  const nextStep = () => {
    if (finished || !started || data.length === 0) return
    
    const nextIndex = currentIndex + 1
    if (nextIndex >= data.length) {
      // 回测结束，强制平仓
      if (tradeInfoRef.current.active && tradeInfoRef.current.entryPrice) {
        const lastCandle = data[data.length - 1]
        const avgCostPrice = props.trader.sell(lastCandle.close)
        if (avgCostPrice && avgCostPrice > 0) {
          setHolding(false)
          addTradeMarker(lastCandle, 'sell', lastCandle.close)
          const entryPrice = tradeInfoRef.current.entryPrice
          const profitRatio = (lastCandle.close - avgCostPrice) / avgCostPrice
          if (!isNaN(profitRatio) && isFinite(profitRatio)) {
            registerTrade(profitRatio, avgCostPrice, lastCandle.close)
          }
        }
        tradeInfoRef.current = {
          active: false,
          entryPrice: 0,
          entryTimestamp: null,
          entryIndex: -1,
          overlayId: null
        }
        setTimeout(() => {
          setFinished(true)
          setAutoRun(false)
          finalize()
        }, 0)
        return
      }
      setFinished(true)
      setAutoRun(false)
      finalize()
      return
    }
    
    setCurrentIndex(nextIndex)
    const actualData = data.slice(0, nextIndex + 1)
    
    evaluateSignals(actualData)
    
    const candle = actualData[actualData.length - 1]
    if (!holding && !tradeInfoRef.current.active) {
      props.trader.hold(candle.close)
    }
    
    recordEquity(candle.timestamp, props.trader.equity)
    
    applyChart(actualData)
  }

  const refreshTradeOverlay = (actualData) => {
    const info = tradeInfoRef.current
    if (!info.active || !props.chart?.current) {
      removeTradeOverlay()
      return
    }
    if (info.entryIndex < 0 || info.entryIndex >= actualData.length) {
      removeTradeOverlay()
      return
    }
    const segment = actualData.slice(info.entryIndex)
    if (!segment.length) {
      removeTradeOverlay()
      return
    }
    // 使用全部数据的最高价和最低价，而不是只使用 segment 的价格
    const maxHigh = Math.max(...actualData.map(bar => bar.high))
    const minLow = Math.min(...actualData.map(bar => bar.low))
    const latestClose = segment[segment.length - 1].close
    const color = latestClose >= info.entryPrice ? 'rgba(255,22,22,0.15)' : 'rgba(13,190,28,0.15)'
    removeTradeOverlay()
    info.overlayId = props.chart.current.createOverlay({
      name: 'rect',
      styles: {
        polygon: {
          color
        }
      },
      points: [
        { timestamp: segment[0].timestamp, value: maxHigh },
        { timestamp: segment[segment.length - 1].timestamp, value: minLow }
      ]
    })
  }

  const createGhostBar = (last) => {
    if (!last) {
      return null
    }
    return {
      open: last.close,
      close: last.close,
      high: last.close,
      low: last.close,
      volume: 0,
      amount: 0,
      timestamp: last.timestamp + 24 * 60 * 60 * 1000
    }
  }

  const applyChart = (actualData) => {
    if (!props.chart?.current) {
      return
    }
    if (!actualData.length) {
      props.chart.current.applyNewData([])
      props.onDataApplied?.([])
      return
    }
    const ghost = createGhostBar(actualData[actualData.length - 1])
    const chartData = ghost ? [...actualData, ghost] : [...actualData]
    props.chart.current.applyNewData(chartData)
    if (props.indicatorStrategies) {
      for (const indicatorStrategy of props.indicatorStrategies) {
        if (indicatorStrategy.reset) {
          indicatorStrategy.reset(props.chart.current)
        }
        indicatorStrategy.update(props.chart.current, chartData)
      }
    }
    // applyNewData 清除了所有 overlay，需要重新绘制买卖标记
    redrawTradeMarkers()
    props.onDataApplied?.(chartData)
    if (actualData.length) {
      const latest = actualData[actualData.length - 1]
      props.setPrice?.(latest.close)
    }
  }

  const evaluateSignals = (actualData) => {
    if (actualData.length < 150) return // 需要足够的数据计算指标（特别是144周期）
    
    const curr = actualData[actualData.length - 1]
    const prev = actualData.length >= 2 ? actualData[actualData.length - 2] : null
    const prev2 = actualData.length >= 3 ? actualData[actualData.length - 3] : null
    const prev3 = actualData.length >= 4 ? actualData[actualData.length - 4] : null
    
    if (!prev || !prev2 || !prev3) return
    
    const currIdx = actualData.length - 1
    const prevIdx = actualData.length - 2
    
    // ========== 信号1: 买线/卖线交叉 ==========
    // 买线:=ZIG(3,10); 卖线:=MA(买线,3);
    const buyLineZig = calculateZIG(actualData, 3, 10)
    if (buyLineZig.length < 3) return
    
    const sellLineMA = []
    for (let i = 0; i < buyLineZig.length; i++) {
      if (i < 2) {
        sellLineMA.push(buyLineZig[i])
      } else {
        const ma3 = calculateMA(buyLineZig.slice(Math.max(0, i - 2), i + 1), 3)
        sellLineMA.push(ma3 !== null ? ma3 : buyLineZig[i])
      }
    }
    const currBuyLine = buyLineZig[currIdx]
    const prevBuyLine = buyLineZig[prevIdx]
    const currSellLine = sellLineMA[currIdx]
    const prevSellLine = sellLineMA[prevIdx]
    
    // 信号1买入：CROSS(买线,卖线)
    const signal1Buy = prevBuyLine <= prevSellLine && currBuyLine > currSellLine
    // 信号1卖出：买线向下穿越卖线
    const signal1Sell = prevBuyLine >= prevSellLine && currBuyLine < currSellLine
    
    // ========== 信号2: B/G 交叉（使用重新定义后的B） ==========
    // 注意：B被重新定义为 ZIG(3,10)，覆盖了之前的EMA(C,2)
    // B:ZIG(3,10); G:=MA(B,2); D:=EMA(B,34);
    const B_ZIG = calculateZIG(actualData, 3, 10)
    const B_MA2 = []
    for (let i = 0; i < B_ZIG.length; i++) {
      if (i < 1) {
        B_MA2.push(B_ZIG[i])
      } else {
        const ma2 = calculateMA(B_ZIG.slice(Math.max(0, i - 1), i + 1), 2)
        B_MA2.push(ma2 !== null ? ma2 : B_ZIG[i])
      }
    }
    const G_B = B_MA2 // G 是 B 的 2 周期 MA
    const D_B = calculateEMA(B_ZIG.map(v => ({ close: v })), 34, 'close') // D:=EMA(B,34)
    
    const currB = B_ZIG[currIdx]
    const prevB = B_ZIG[prevIdx]
    const currG = G_B[currIdx]
    const prevG = G_B[prevIdx]
    const currD_B = D_B[currIdx]
    
    // 信号2买入：根据 VERLINE(CROSS(B,G) AND (A1 AND A2 OR D<0),1)
    // 注意：这里的D是EMA(B,34)，B是ZIG(3,10)
    // A1和A2使用重新计算后的S1/S2（但由于公式相同，结果应该一样）
    const signal2Buy_Simple = prevB <= prevG && currB > currG
    
    // 完整买入条件：CROSS(B,G) AND (A1 AND A2 OR D<0)
    // 注意：这里的A1/A2应该使用当前计算的值（它们使用的是相同的S1/S2/MR公式）
    const signal2Buy = signal2Buy_Simple && (A1 && A2 || currD_B < 0)
    
    // 信号2卖出：CROSS(G,B) - G向上穿越B（即B向下穿越G）
    const signal2Sell = prevB >= prevG && currB < currG
    
    // ========== 信号3: 复杂买入条件 AA ==========
    // W:ZIG(1,3); G:=MA(W,2); B:EMA(C,2); D:=EMA(W,34);
    const W = calculateZIG(actualData, 1, 3) // W:ZIG(1,3) - 基于收盘价
    const W_MA2 = []
    for (let i = 0; i < W.length; i++) {
      if (i < 1) {
        W_MA2.push(W[i])
      } else {
        const ma2 = calculateMA(W.slice(Math.max(0, i - 1), i + 1), 2)
        W_MA2.push(ma2 !== null ? ma2 : W[i])
      }
    }
    const WG = W_MA2 // G 是 W 的 2 周期 MA
    const WB = calculateEMA(actualData, 2, 'close') // B:EMA(C,2)
    const WD = calculateEMA(W.map(v => ({ close: v })), 34, 'close') // D:=EMA(W,34)
    
    // F:=100*(C-REF(C,1))/REF(C,1); JD:=IF(C<REF(O,1) AND F<0,1,0);
    const F = []
    const JD = []
    const S1 = []
    const MR = []
    for (let i = 0; i < actualData.length; i++) {
      if (i === 0) {
        F.push(0)
        JD.push(0)
        S1.push(0)
        MR.push(0)
      } else {
        const prevC = actualData[i - 1].close
        const currC = actualData[i].close
        const f = 100 * (currC - prevC) / prevC
        F.push(f)
        const jd = (currC < actualData[i].open && f < 0) ? 1 : 0
        JD.push(jd)
        S1.push(jd)
        
        if (i >= 2) {
          const mr = (currC < actualData[i - 2].open && f < 0) ? 1 : 0
          MR.push(mr)
        } else {
          MR.push(0)
        }
      }
    }
    
    // A1:=S1=0 AND REF(S1,1)=1 AND S2=0 AND REF(S2,1)=1 AND CROSS(ZIG(3,3),REF(ZIG(3,3),1))
    // A2:=S1=0 AND REF(S1,1)=1 AND S2=0 AND REF(S2,1)=1 AND CROSS(ZIG(3,5),REF(ZIG(3,5),1))
    const ZIG33 = calculateZIG(actualData, 3, 3)
    const ZIG35 = calculateZIG(actualData, 3, 5)
    const S2 = MR
    
    const currS1 = S1[currIdx]
    const prevS1 = S1[prevIdx]
    const currS2 = S2[currIdx]
    const prevS2 = S2[prevIdx]
    
    // CROSS(ZIG(3,3), REF(ZIG(3,3),1)) 表示 ZIG(3,3) 向上穿越前一周期的值
    // 即：prev <= REF(prev,1) AND curr > prev
    const currZIG33 = ZIG33[currIdx]
    const prevZIG33 = ZIG33[prevIdx]
    const prevPrevZIG33 = ZIG33.length >= 3 ? ZIG33[prevIdx - 1] : prevZIG33
    const crossZIG33 = prevZIG33 <= prevPrevZIG33 && currZIG33 > prevZIG33
    
    const currZIG35 = ZIG35[currIdx]
    const prevZIG35 = ZIG35[prevIdx]
    const prevPrevZIG35 = ZIG35.length >= 3 ? ZIG35[prevIdx - 1] : prevZIG35
    const crossZIG35 = prevZIG35 <= prevPrevZIG35 && currZIG35 > prevZIG35
    
    const A1 = currS1 === 0 && prevS1 === 1 && currS2 === 0 && prevS2 === 1 && crossZIG33
    const A2 = currS1 === 0 && prevS1 === 1 && currS2 === 0 && prevS2 === 1 && crossZIG35
    
    const currW = W[currIdx]
    const prevW = W[prevIdx]
    const currWG = WG[currIdx]
    const prevWG = WG[prevIdx]
    const currWB = WB[currIdx]
    const prevWB = WB[prevIdx]
    const currWD = WD[currIdx]
    
    // CROSS(W,G) - W向上穿越G
    const crossWG = prevW <= prevWG && currW > currWG
    // CROSS(B,G) - 注意这里的B是EMA(C,2)，G是MA(W,2)
    const crossWB = prevWB <= prevWG && currWB > WG[currIdx]
    
    // AA:=(CROSS(W,G) AND (A1 AND A2 OR D<0)) OR CROSS(B,G)
    // 注意：这里的D是EMA(W,34)
    const signal3Buy = (crossWG && (A1 && A2 || currWD < 0)) || crossWB
    
    // ========== 信号4: 顶部卖出信号 ==========
    // VAR3:=PEAKBARS(3,5,1)<10; 顶:=IF(VAR3=1,2,0); 顶A:=IF(顶>REF(顶,1),1,0)
    // 注意：这里的B指的是信号2中的B，即ZIG(3,10)
    const peakBars = calculatePEAKBARS(actualData, 3, 5, 1)
    const currPeakBars = peakBars[currIdx]
    const VAR3 = currPeakBars !== null && currPeakBars < 10 ? 1 : 0
    const 顶 = VAR3 === 1 ? 2 : 0
    const prevPeakBars = peakBars[prevIdx] !== null && peakBars[prevIdx] < 10 ? 1 : 0
    const prev顶 = prevPeakBars === 1 ? 2 : 0
    const 顶A = 顶 > prev顶 ? 1 : 0
    const signal4Sell = 顶A === 1
    
    // ========== 信号5: 其他买点 ==========
    // 买点1:=Var10:=IF(TROUGHBARS(3,16,1)=0 AND HIGH>LOW+0.04,4,0)
    const troughBars = calculateTROUGHBARS(actualData, 3, 16, 1)
    const currTroughBars = troughBars[currIdx]
    const Var10 = (currTroughBars === 0 && curr.high > curr.low + 0.04) ? 4 : 0
    const 买点1 = Var10 > 0
    
    // 买点2:=(Var11+Var13+Var15+Var17)
    const ZIG36 = calculateZIG(actualData, 3, 6)
    const ZIG322 = calculateZIG(actualData, 3, 22)
    const ZIG351 = calculateZIG(actualData, 3, 51)
    const ZIG372 = calculateZIG(actualData, 3, 72)
    
    const checkZIGUp = (zig, idx) => {
      if (idx < 3) return false
      const curr = zig[idx]
      const prev1 = zig[idx - 1]
      const prev2 = zig[idx - 2]
      const prev3 = zig[idx - 3]
      return curr > prev1 && prev1 <= prev2 && prev2 <= prev3
    }
    
    const Var11 = checkZIGUp(ZIG36, currIdx) ? 1 : 0
    const Var13 = checkZIGUp(ZIG322, currIdx) ? 1 : 0
    const Var15 = checkZIGUp(ZIG351, currIdx) ? 1 : 0
    const Var17 = checkZIGUp(ZIG372, currIdx) ? 1 : 0
    const 买点2 = (Var11 + Var13 + Var15 + Var17) > 0
    
    // 综合买入信号
    const buySignal = signal1Buy || signal2Buy || signal3Buy || 买点1 || 买点2
    
    // 综合卖出信号
    const sellSignal = signal1Sell || signal2Sell || signal4Sell
    
    let traded = false
    
    // 执行买入
    if (buySignal && !holding) {
      props.trader.buy(curr.close)
      setHolding(true)
      addTradeMarker(curr, 'buy', curr.close)
      tradeInfoRef.current = {
        active: true,
        entryPrice: curr.close,
        entryTimestamp: curr.timestamp,
        entryIndex: actualData.length - 1,
        overlayId: tradeInfoRef.current.overlayId
      }
      traded = true
      console.log('✅ Spring 买入:', {
        price: curr.close,
        signals: {
          signal1: signal1Buy,
          signal2: signal2Buy,
          signal3: signal3Buy,
          买点1,
          买点2
        },
        timestamp: curr.timestamp
      })
    }
    
    // 执行卖出
    if (sellSignal && holding && !traded) {
      const avgCostPrice = props.trader.sell(curr.close)
      if (!avgCostPrice || avgCostPrice <= 0) {
        console.warn('⚠️ Spring 卖出失败：avgCostPrice 无效', { avgCostPrice, entryPrice: tradeInfoRef.current.entryPrice })
        return
      }
      setHolding(false)
      addTradeMarker(curr, 'sell', curr.close)
      if (tradeInfoRef.current.overlayId && props.chart?.current) {
        overlaysRef.current.push(tradeInfoRef.current.overlayId)
      }
      const entryPrice = tradeInfoRef.current.entryPrice
      const profitRatio = (curr.close - avgCostPrice) / avgCostPrice
      if (isNaN(profitRatio) || !isFinite(profitRatio)) {
        console.warn('⚠️ Spring 卖出失败：profitRatio 计算错误', { 
          close: curr.close, 
          avgCostPrice, 
          entryPrice,
          profitRatio 
        })
        return
      }
      registerTrade(profitRatio, avgCostPrice, curr.close)
      console.log('✅ Spring 卖出:', {
        entryPrice,
        avgCostPrice,
        exitPrice: curr.close,
        profitRatio: ((curr.close - avgCostPrice) / avgCostPrice * 100).toFixed(2) + '%',
        signals: {
          signal1: signal1Sell,
          signal2: signal2Sell,
          signal4: signal4Sell
        },
        timestamp: curr.timestamp
      })
      tradeInfoRef.current = {
        active: false,
        entryPrice: 0,
        entryTimestamp: null,
        entryIndex: -1,
        overlayId: null
      }
      traded = true
    }
    
    if (!traded && tradeInfoRef.current.active) {
      refreshTradeOverlay(actualData)
    }
  }

  const endBacktest = () => {
    setAutoRun(false)
    setFinished(true)
    finalize()
  }

  return (
    <>
      {SummaryModal}
      <div style={{
        display: 'flex',
        flexDirection: 'column',
        gap: 8,
        padding: '8px 12px',
        backgroundColor: 'rgba(26, 26, 26, 0.95)',
        borderRadius: 4
      }}>
        {!started ? (
          <button onClick={loadRandomDataset}>开始回测</button>
        ) : (
          <>
            <div style={{display: 'flex', gap: 8}}>
              <button onClick={nextStep} disabled={finished || autoRun}>步进</button>
              <button
                onClick={() => {
                  setAutoRun(prev => !prev)
                }}
              >
                {autoRun ? '停止自动' : '自动'}
              </button>
              <div style={{display: 'flex', alignItems: 'center', gap: 6}}>
                <div style={{color: 'rgba(255,255,255,0.65)', fontSize: 12}}>速度</div>
                <input
                  type="range"
                  min={100}
                  max={5000}
                  step={100}
                  value={intervalMs}
                  onChange={e => setIntervalMs(Number(e.target.value))}
                  style={{width: 160}}
                />
                <div style={{minWidth: 50, textAlign: 'right', color: '#0dd697', fontSize: 12}}>{(intervalMs / 1000).toFixed(1)}s</div>
              </div>
              <button onClick={endBacktest}>结束</button>
            </div>
          </>
        )}
      </div>
    </>
  )
}

export default { update, name: 'Spring', comment, Tools: SpringTools }

